package com.pxl.springbootinit.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pxl.springbootinit.common.ErrorCode;
import com.pxl.springbootinit.exception.BusinessException;
import com.pxl.springbootinit.model.dto.task.TaskClaimForm;
import com.pxl.springbootinit.model.dto.task.TaskForm;
import com.pxl.springbootinit.model.entity.Task;
import com.pxl.springbootinit.model.entity.TaskClaim;
import com.pxl.springbootinit.model.entity.User;
import com.pxl.springbootinit.model.enums.ReviewStatusEnum;
import com.pxl.springbootinit.model.enums.TaskStatusEnum;
import com.pxl.springbootinit.model.vo.TaskClaimVO;
import com.pxl.springbootinit.service.TaskClaimService;
import com.pxl.springbootinit.mapper.TaskClaimMapper;
import com.pxl.springbootinit.service.TaskService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
* @author MADAO
* @description 针对表【task_claim(任务认领表)】的数据库操作Service实现
* @createDate 2024-12-20 11:59:03
*/
@Service
public class TaskClaimServiceImpl extends ServiceImpl<TaskClaimMapper, TaskClaim>
    implements TaskClaimService{
    private static final ReentrantLock lock = new ReentrantLock();

    @Resource
    private TaskService taskService;

    /**
     * 领取任务
     *
     * @param taskClaimForm
     * @param user
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean claimTask(TaskClaimForm taskClaimForm, User user) {
        lock.lock();
        try {
            Long taskId = taskClaimForm.getTaskId();
            Task task = taskService.getById(taskId);
            if (task == null){
                throw new BusinessException(ErrorCode.SYSTEM_ERROR,"任务不存在");
            }
            if (!task.getStatus().equals(TaskStatusEnum.PENDING.getValue())){
                throw new BusinessException(ErrorCode.OPERATION_ERROR,"任务已被领取");
            }
            task.setStatus(TaskStatusEnum.IN_PROGRESS.getValue());
            TaskClaim taskClaim = new TaskClaim();
            BeanUtils.copyProperties(taskClaimForm, taskClaim);
            taskClaim.setUserId(user.getId());
            taskClaim.setAddress(user.getAddress());
            taskClaim.setPhone(user.getPhone());
            taskClaim.setStatus(ReviewStatusEnum.PENDING.getValue());
            if(!(this.save(taskClaim) && taskService.updateById(task))){
                throw new BusinessException(ErrorCode.SYSTEM_ERROR,"领取失败，请重试");
            }
            return true;
        }finally {
            lock.unlock();
        }
    }

    @Override
    public List<TaskClaimVO> userClaimedTask(Long userId) {
        if (userId == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户ID不能为空");
        }
        QueryWrapper<TaskClaim> taskClaimQueryWrapper = new QueryWrapper<>();
        taskClaimQueryWrapper.eq("user_id",userId);
        List<TaskClaim> taskClaimList = this.list(taskClaimQueryWrapper);
        if (taskClaimList == null && taskClaimList.isEmpty()){
            return new ArrayList<>();
        }

        List<Long> taskIdList = new ArrayList<>(taskClaimList.size());
        taskClaimList.forEach(taskClaim -> {
            taskIdList.add(taskClaim.getTaskId());
        });
        Map<Long, Task> map = taskService.listByIds(taskIdList).stream()
                .collect(Collectors.toMap(Task::getId, task -> task));

        return taskClaimList.stream().map(taskClaim -> {
            TaskClaimVO taskClaimVO = new TaskClaimVO();
            BeanUtils.copyProperties(taskClaim, taskClaimVO);
            Task task = map.get(taskClaim.getTaskId());
            taskClaimVO.setTask(taskService.getTaskVO(task));
            return taskClaimVO;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancelTask(Long taskId) {
        Task task = taskService.getById(taskId);
        if (task == null){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"任务不存在");
        }
        task.setStatus(TaskStatusEnum.PENDING.getValue());
        QueryWrapper<TaskClaim> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("task_id",taskId);
        if (!(taskService.updateById(task) && this.remove(queryWrapper))){
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        return true;
    }

    @Override
    public Page<TaskClaimVO> pageTask(TaskForm taskForm) {
        int current = taskForm.getCurrent();
        int pageSize = taskForm.getPageSize();
        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(taskForm.getTitle() != null,"title",taskForm.getTitle());
        queryWrapper.like(taskForm.getDescription() != null,"description",taskForm.getDescription());
        queryWrapper.eq(taskForm.getTaskType() != null,"task_type",taskForm.getTaskType());
        queryWrapper.eq(taskForm.getStatus() != null,"status",taskForm.getStatus());
        Page<Task> taskPage = taskService.page(new Page<>(current, pageSize), queryWrapper);
        List<Long> taskIdList = taskPage.getRecords().stream().map(Task::getId).collect(Collectors.toList());
        Map<Long, TaskClaim> taskClaimMap = this.list(new QueryWrapper<TaskClaim>().in("task_id", taskIdList))
                .stream().collect(Collectors.toMap(TaskClaim::getTaskId, taskClaim -> taskClaim));

        List<TaskClaimVO> taskClaimVOList = taskPage.getRecords().stream().map(task -> {
            TaskClaimVO taskClaimVO = new TaskClaimVO();
            TaskClaim taskClaim = taskClaimMap.get(task.getId());
            if (taskClaim != null){
                BeanUtils.copyProperties(taskClaim, taskClaimVO);
            }
            taskClaimVO.setTask(taskService.getTaskVO(task));
            return taskClaimVO;
        }).collect(Collectors.toList());

        Page<TaskClaimVO> claimVOPage = new Page<>();
        claimVOPage.setTotal(taskPage.getTotal());
        claimVOPage.setPages(taskPage.getPages());
        claimVOPage.setRecords(taskClaimVOList);
        return claimVOPage;
    }

    @Override
    public Boolean passTaskClaim(Long taskId) {
        if (taskId == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"任务ID不能为空");
        }
        QueryWrapper<TaskClaim> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("task_id",taskId);
        TaskClaim taskClaim = this.getOne(queryWrapper);
        if (taskClaim == null){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"任务不存在");
        }
        taskClaim.setStatus(ReviewStatusEnum.APPROVED.getValue());
        boolean result = this.updateById(taskClaim);
        if (!result){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"审批失败，请重试");
        }
        return true;
    }

    @Override
    public Boolean rejectTaskClaim(Long taskId) {
        if (taskId == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"任务ID不能为空");
        }
        QueryWrapper<TaskClaim> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("task_id",taskId);
        TaskClaim taskClaim = this.getOne(queryWrapper);
        if (taskClaim == null){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"任务不存在");
        }
        taskClaim.setStatus(ReviewStatusEnum.REJECTED.getValue());
        boolean result = this.updateById(taskClaim);
        if (!result){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"审批失败，请重试");
        }
        return true;
    }

    @Override
    public Page<TaskClaimVO> pageAdminTask(TaskForm taskForm) {
        int current = taskForm.getCurrent();
        int pageSize = taskForm.getPageSize();
        QueryWrapper<TaskClaim> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(taskForm.getStatus() != null,"status",taskForm.getStatus());
        queryWrapper.orderByDesc("updated_time");
        Page<TaskClaim> taskClaimPage = this.page(new Page<TaskClaim>(current, pageSize), queryWrapper);
        List<Long> taskIdList = taskClaimPage.getRecords().stream().map(TaskClaim::getTaskId).collect(Collectors.toList());
        Map<Long, Task> taskMap = taskService.listByIds(taskIdList).stream().collect(Collectors.toMap(Task::getId, task -> task));

        List<TaskClaimVO> collect = taskClaimPage.getRecords().stream().map(taskClaim -> {
            TaskClaimVO taskClaimVO = new TaskClaimVO();
            BeanUtils.copyProperties(taskClaim, taskClaimVO);
            Task task = taskMap.get(taskClaim.getTaskId());
            taskClaimVO.setTask(taskService.getTaskVO(task));
            taskClaimVO.setTitle(task.getTitle());
            return taskClaimVO;
        }).collect(Collectors.toList());
        Page<TaskClaimVO> claimVOPage = new Page<>();
        claimVOPage.setTotal(taskClaimPage.getTotal());
        claimVOPage.setRecords(collect);
        return claimVOPage;
    }

}




